home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src.arc / TIMER.C < prev    next >
C/C++ Source or Header  |  1989-08-19  |  4KB  |  180 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "timer.h"
  4. #include "proc.h"
  5. #include "pc.h"
  6.  
  7. static struct timer *Timers;    /* Head of running timer chain */
  8. int32 Clock;
  9.  
  10. void
  11. timerproc(i,v1,v2)
  12. int i;
  13. void *v1,*v2;
  14. {
  15.     register struct timer *t;
  16.     register struct timer *expired = NULLTIMER;
  17.     char i_state;
  18.  
  19.     for(;;){
  20.         i_state = dirps();    /* Tick is modified by an interrupt */
  21.         while(Tick == 0)
  22.             pwait(&Tick);
  23.         Tick--;
  24.         restore(i_state);
  25.  
  26.         Clock++;
  27.         systick();    /* Machine-dependent per-tick stuff */
  28.  
  29.         /* Decrement the first timer. If it expires,
  30.          * take it off the running list and put it
  31.          * on a singly linked list of expired timers
  32.          */
  33.         if(Timers != NULLTIMER)
  34.             Timers->count--;
  35.         else
  36.             continue;    /* Nothing else on this tick */
  37.  
  38.         while(Timers != NULLTIMER && Timers->count <= 0){
  39.             if(Timers->next == Timers){
  40.                 printf("PANIC: Timer loop at %lx\n",
  41.                  (long)Timers);
  42.                 iostop();
  43.                 exit(1);
  44.             }
  45.             /* Save Timers since stop_timer will change it */
  46.             t = Timers;
  47.             stop_timer(t);
  48.             t->state = TIMER_EXPIRE;
  49.             /* Add to expired timer list */
  50.             t->next = expired;
  51.             expired = t;
  52.         }
  53.         /* Now go through the list of expired timers, removing each
  54.          * one and kicking the notify function, if there is one
  55.          */
  56.         while((t = expired) != NULLTIMER){
  57.             expired = t->next;
  58.             if(t->func){
  59.                 (*t->func)(t->arg);
  60.             }
  61.         }
  62.     }
  63. }
  64. /* Start a timer */
  65. void
  66. start_timer(t)
  67. struct timer *t;
  68. {
  69.     register struct timer *tnext,*tprev;
  70.     int32 tot;
  71.  
  72.     if(t == NULLTIMER)
  73.         return;
  74.     if(t->state == TIMER_RUN)
  75.         stop_timer(t);
  76.     if(t->start == 0)
  77.         return;        /* A start value of 0 disables the timer */
  78.  
  79.     t->state = TIMER_RUN;
  80.     /* Find right place on list for this guy */
  81.     tot = 0;
  82.     tprev = NULLTIMER;
  83.     for(tnext = Timers;tnext != NULLTIMER;tnext = tprev->next){
  84.         if(tnext->count + tot > t->start)
  85.             break;
  86.         tprev = tnext;
  87.         tot += tnext->count;
  88.     }
  89.     /* At this point, tprev points to the entry that should go right
  90.      * before us, and tnext points to the entry just after us. Either or
  91.      * both may be null.
  92.      */
  93.     t->count = t->start - tot;    /* Adjust for entries before us */
  94.     if((t->prev = tprev) == NULLTIMER)
  95.         Timers = t;        /* Put at beginning */
  96.     else
  97.         tprev->next = t;
  98.  
  99.     if((t->next = tnext) != NULLTIMER){
  100.         tnext->prev = t;
  101.         /* Adjust the following entry's count */
  102.         tnext->count -= t->count;
  103.     }
  104. }
  105. /* Stop a timer */
  106. void
  107. stop_timer(t)
  108. register struct timer *t;
  109. {
  110.     register struct timer *tp;
  111.  
  112.     if(t == NULLTIMER)
  113.         return;
  114.     if(t->state == TIMER_RUN){
  115.         /* Delete from active timer list */
  116.         if(t->next != NULLTIMER)
  117.             t->next->prev = t->prev;
  118.         if(t->prev != NULLTIMER)
  119.             t->prev->next = t->next;
  120.         else
  121.             Timers = t->next;
  122.         /* Adjust count for the next timer */
  123.         if((tp = t->next) != NULLTIMER)
  124.             tp->count += t->count;
  125.     }
  126.     t->state = TIMER_STOP;
  127. }
  128. /* Return count of ticks remaining on this timer */
  129. int32
  130. read_timer(t)
  131. struct timer *t;
  132. {
  133.     register struct timer *tp;
  134.     int32 tot;
  135.  
  136.     if(t->state != TIMER_RUN)
  137.         return 0;
  138.  
  139.     tot = 0;
  140.     for(tp = Timers;tp != NULLTIMER; tp = tp->next){
  141.         tot += tp->count;
  142.         if(tp == t)
  143.             break;
  144.     }
  145.     return tot;
  146. }
  147. /* Delay process for specified number of ticks */
  148. void
  149. pause(ticks)
  150. int32 ticks;
  151. {
  152.     if(Curproc == NULLPROC || ticks == 0)
  153.         return;
  154.     alarm(ticks);
  155.     /* The actual event doesn't matter, since we'll be alerted */
  156.     while(Curproc->alarm.state == TIMER_RUN && pwait(Curproc) == 1)
  157.         ;
  158.  
  159.     alarm(0L); /* Make sure it's stopped, in case we were killed */    
  160. }
  161. static void
  162. t_alarm(x)
  163. void *x;
  164. {
  165.     alert((struct proc *)x,1);
  166. }
  167. /* Send signal to current process after specified number of ticks */
  168. void
  169. alarm(ticks)
  170. int32 ticks;
  171. {
  172.     if(Curproc != NULLPROC){
  173.         Curproc->alarm.start = ticks;
  174.         Curproc->alarm.func = t_alarm;
  175.         Curproc->alarm.arg = (char *)Curproc;
  176.         start_timer(&Curproc->alarm);
  177.     }
  178. }
  179.     
  180.